package org.dreamwork.tools.sdq;

import org.dreamwork.concurrent.Looper;
import org.dreamwork.tools.sdq.conf.ServerConfig;
import org.dreamwork.tools.sdq.model.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class QueueServer {
    private static final String LOOPER_NAME = "queue.server";
    private final ServerConfig config;
    private BlockingQueue<Message> queue;
    private final LoadBalancer balancer;
    private final Logger logger = LoggerFactory.getLogger (QueueServer.class);

    private DatagramSocket server;
    private DatagramPacket packet;

    private transient boolean running = true;
    private Thread thread;

    public QueueServer () {
        config = new ServerConfig ();
        config.setQueueCapacity (1024);
        config.setHealthCheckInterval (1000);
        config.setUdpPort (56789);
        balancer = new LoadBalancer (config);
        init ();
    }

    public QueueServer (ServerConfig config) {
        this.config = config;
        balancer = new LoadBalancer (config);
        init ();
    }

    public void bind () throws IOException {
        int port = config.getUdpPort ();
        if (port <= 0) {
            throw new IOException ("cannot bind server on port: " + port);
        }


        Looper.create (LOOPER_NAME, 16, 16);
        server = new DatagramSocket (port);
        server.setReuseAddress (true);
        server.setReceiveBufferSize (1024);
        thread = new Thread (this::receive);
    }

    public void unbind () {
        running = false;
        thread.interrupt ();
        server.close ();
    }

    private void receive () {
        while (running && !thread.isInterrupted ()) {
            try {
                byte[] buff = new byte[1024];
                DatagramPacket packet = new DatagramPacket (buff, 0, 1024);
                server.receive (packet);

                int length = packet.getLength ();
                final byte[] data = new byte[length];
                System.arraycopy (buff, 0, data, 0, length);
                Looper.runInLoop (LOOPER_NAME, () -> {

                });
            } catch (IOException e) {
                throw new RuntimeException (e);
            }
        }
    }

    private void init () {
        queue = new LinkedBlockingQueue<> (config.getQueueCapacity ());
        balancer.start ();
    }
}